package models

import (
	"cgs-server/helper"
	"cgs-server/server/cgs/app/models/filter"
	"cgs-server/server/model"
	"errors"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"strconv"
	"strings"
)

const (
	UpdateRow = "update_row"
	DeleteRow = "delete_row"
	AddRow    = "add_row"
)

type WorksheetRow struct {
	RowId       string  `json:"rowId" bson:"rowId"`
	WorksheetId string  `json:"worksheetId" bson:"worksheetId"`
	Data        RowData `json:"data,inline" bson:"data,inline"`

	hasTransfer bool

	// RelationRowId 关联表 rowId
	RelationRowId string `json:"relationRowId,omitempty" bson:"relationRowId,omitempty"`

	model.BaseModel `json:",inline" bson:",inline"`
}

func (w *WorksheetRow) SetId(id primitive.ObjectID) {
	w.RowId = id.Hex()
}

func (w *WorksheetRow) GetId() string {
	return w.RowId
}

func (w *WorksheetRow) CollectionName() string {
	return "ws" + w.WorksheetId
}

func (w *WorksheetRow) SubFormRowData(fields *Fields) RowData {
	if fields == nil {
		return nil
	}
	rowData := RowData{}
	for _, field := range *fields {
		if field.IsSubForm() {
			data := w.Data.DataByName(field.Name)
			if data != nil {
				rowData[field.Name] = data
				w.Data.DeleteByName(field.Name)
			}
		}
	}

	return rowData
}

type RowData map[string]interface{}

func (w *WorksheetRow) TransferData(fields *Fields, user *model.User) error {
	if w.Data == nil {
		return errors.New("row data is nil")
	}
	if w.hasTransfer {
		return nil
	}
	// rowData 里面可能会包含子表的数据，需要分离出来
	rowData, err := w.Data.TransferData(fields, user)
	if err != nil {
		return err
	}
	w.hasTransfer = true
	w.Data = rowData
	return nil
}
func (w *WorksheetRow) FormatData(fields *Fields) error {
	if w.Data == nil {
		return errors.New("row data is nil")
	}
	rowData, err := w.Data.FormatData(fields)
	if err != nil {
		return err
	}
	w.Data = rowData
	return nil
}

func (rowData *RowData) DataByName(name string) interface{} {
	if d, ok := (*rowData)[name]; ok {
		return d
	}
	return nil
}

func (rowData *RowData) DeleteByName(name string) {
	delete(*rowData, name)
}

func (rowData *RowData) TransferData(fields *Fields, user *model.User) (RowData, error) {
	if fields == nil {
		return nil, errors.New("fields is nil")
	}

	doc := RowData{}

	for k, v := range *rowData {
		field := fields.GetField(k)
		if field == nil {
			continue
		}
		//dataType, fieldOptions := fields.GetDataTypeAndOptions(k)
		dataType, fieldOptions := field.DataType, field.Options
		switch dataType {
		case filter.Num:
			if str, ok := v.(string); ok && str != "" {
				number, err := strconv.ParseFloat(str, 64)
				if err != nil {
					doc[k] = v
					continue
				}
				doc[k] = number
			} else {
				doc[k] = v
			}
		case filter.DATE:
			if v == nil {
				doc[k] = v
			} else if fieldOptions != nil {
				format := fieldOptions.Value("valueFormat").(string)
				timeStr := v.(string)
				if len(timeStr) > len(format) {
					timeStr = strings.Split(timeStr, " ")[0]
				}
				t, err := helper.StringToTime(timeStr, format)
				if err != nil {
					return nil, err
				}
				doc[k] = t
			} else {
				doc[k] = v
			}
		case filter.Member:
			if v == nil {
				doc[k] = v
			} else {
				memberData, ok := v.(map[string]interface{})
				if !ok {
					continue
				}
				memberType := memberData["memberType"]
				if memberType == "currentUser" {
					memberData["label"] = user.Name
					memberData["userId"] = user.UserId
					doc[k] = memberData
				}
			}

			//case filter.DetailTable:
		//	// 子表，数据是一个数组
		//	_ = v
		//	dataArr, ok := v.([]interface{})
		//	if !ok {
		//		continue
		//	}
		//	values := make([]interface{}, 0, len(dataArr))
		//	for _, d := range dataArr {
		//		data, ok := d.(map[string]interface{})
		//		if !ok {
		//			continue
		//		}
		//		row := RowData(data)
		//		transferData, err := row.TransferData(field.SubFields)
		//		if err != nil {
		//			return nil, err
		//		}
		//		values = append(values, transferData)
		//	}
		//	doc[k] = values
		case filter.NotExitType:
			// 无此字段
		default:
			doc[k] = v
		}
	}

	return doc, nil
}

func NeedFormat(fields *Fields) bool {
	needFormat := false
	for _, field := range *fields {
		if field.DataType == filter.DATE {
			needFormat = true
			break
		}
	}
	return needFormat
}

// FormatData 格式化表单数据，会根据字段 options 中的配置去格式化
func (rowData *RowData) FormatData(fields *Fields) (RowData, error) {
	if fields == nil {
		return nil, errors.New("fields is nil")
	}

	//needFormat := NeedFormat(fields)
	//if !needFormat {
	//	return *rowData, nil
	//}

	return rowData.slowFormat(fields)
}

func (rowData *RowData) slowFormat(fields *Fields) (RowData, error) {
	doc := RowData{}

	for k, v := range *rowData {
		dataType, fieldOptions := fields.GetDataTypeAndOptions(k)
		switch dataType {
		case filter.DATE:
			if v == nil {
				doc[k] = v
				continue
			}
			if _, ok := v.(string); ok {
				doc[k] = v
				continue
			}
			if fieldOptions != nil {
				format := fieldOptions.Value("valueFormat").(string)
				timeStr := helper.Format(v.(primitive.DateTime).Time(), format)
				doc[k] = timeStr
			} else {
				timeStr := helper.Format(v.(primitive.DateTime).Time(), "YYYY-MM-DD HH:mm:ss")
				doc[k] = timeStr
			}
		case filter.NotExitType:
			// 无此字段
		default:
			doc[k] = v
		}
	}

	return doc, nil
}

type WorksheetRows struct {
	WorksheetId   string     `json:"worksheetId" bson:"worksheetId"`
	Rows          *[]RowData `json:"rows" bson:"rows"`
	RelationRowId string     `json:"relationRowId,omitempty" bson:"relationRowId,omitempty"`
}

func (w *WorksheetRows) GetWsRowData() []*WorksheetRow {
	result := []*WorksheetRow{}
	if len(*w.Rows) == 0 {
		return result
	}
	for _, v := range *w.Rows {
		result = append(result, &WorksheetRow{
			WorksheetId:   w.WorksheetId,
			Data:          v,
			RelationRowId: w.RelationRowId,
		})
	}
	return result
}
